/*
 * 础光实时操作系统PhotonRTOS -- 调度表功能测试代码
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Lin Yang <s-yanglin@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include "../functest.h"

#define IdCounter		2
#define IdScheduleTable0	0
#define IdScheduleTable1	1
#define IdTestTask7		7
#define IdTestTask8		8
#define EVENT7_1		0x1
#define TASK7_ACTIVATED		101
#define TASK7_EVENT_WAKEUP	102
#define TASK8_ACTIVATED		103
#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
#define IdTestTask9		9
#define EVENT9_1		0x1
#define EVENT9_2		0x2
#define TASK9_ACTIVATED		104
#define TASK9_EVENT_WAKEUP1	105
#define TASK9_EVENT_WAKEUP2	106
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */

uint32 magic;

VAR(uint8, AUTOMATIC) basic_scheduletable_sequence_right[MAX_SEQUENCE] = {
	1, 2, 3, TASK7_ACTIVATED, TASK7_EVENT_WAKEUP, 4, TASK7_ACTIVATED,
	5, TASK7_EVENT_WAKEUP, 6, 7, 8, TASK7_ACTIVATED, TASK7_EVENT_WAKEUP, 9,
	10, 11, TASK7_ACTIVATED, TASK7_EVENT_WAKEUP, 12, TASK7_ACTIVATED, 13,
	TASK7_EVENT_WAKEUP, 14, 15, TASK8_ACTIVATED, 16, 17, 18, SEQUENCE_END,
};

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
VAR(uint8, AUTOMATIC) sync_scheduletable_sequence_right[MAX_SEQUENCE] = {
	1, 2, 3, 4, 5, 6, 7, TASK9_ACTIVATED, 8, 9, 10, TASK9_EVENT_WAKEUP1,
	11, 12, 13, TASK9_EVENT_WAKEUP2, 14, 15, 16, 17, 18, 19, TASK9_ACTIVATED,
	20, 21, 22, TASK9_EVENT_WAKEUP1, 23, 24, 25, TASK9_EVENT_WAKEUP2, 26, 27,
	28, 29, TASK9_ACTIVATED, 30, 31, TASK9_EVENT_WAKEUP1, 32, 33,
	TASK9_EVENT_WAKEUP2, 34, 35, SEQUENCE_END,
};
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */


TEST(basic_scheduletable)
{
	VAR(int32_t, AUTOMATIC) counter_value;
	VAR(int32_t, AUTOMATIC) schedtbl_value = -1;
	VAR(int32_t, AUTOMATIC) schedtbl_cycle = -1;

	DeclareCounter(IdCounter, 1024, 1, 1, SOFTWARE);
	DeclareScheduleTable(IdScheduleTable0, 5, 5, IdCounter, NO_SYNC, 1);
	DeclareExpiryPoint(0, 2, IdScheduleTable0, 0, 0);
	DeclareExpiryPoint(1, 3, IdScheduleTable0, 0, 0);
	DeclareExpiryPoint(2, 4, IdScheduleTable0, 0, 0);
	DeclareExpiryPointTask(0, IdTestTask7, 0);
	DeclareExpiryPointTask(1, IdTestTask7, 1);
	DeclareExpiryPointEvent(0, IdTestTask7, EVENT7_1, 0);
	DeclareExpiryPointEvent(1, IdTestTask7, EVENT7_1, 2);

	DeclareScheduleTable(IdScheduleTable1, 5, 0, IdCounter, NO_SYNC, 1);
	DeclareExpiryPoint(3, 1, IdScheduleTable1, 0, 0);
	DeclareExpiryPointTask(2, IdTestTask8, 3);

	LOGI("基础调度表测试开始\n");
	LOGI("调度表0,周期5,循环,不同步,在2,3,4时刻有到期点\n");
	LOGI("到期点会激活task7，或者给task7设置事件\n");
	LOGI("调度表1,周期5,不循环,不同步,在1时刻有到期点\n");
	LOGI("到期点会激活task8\n");
	LOGI("以下第一列数字是计数器的值\n");
	LOGI("  括号中的数字是调度表已经进行的时刻\n");
	LOGI("  中间两列已激活和事件唤醒的字样来自激活或唤醒的任务输出\n");
	LOGI("  最后一列是当时调用的接口及参数\n");

	StartScheduleTableRel(0, 1);
	magic = 0;
	while (magic < 5) {
		printk("\t");
		magic++;
	}
	printk("StartScheduleTableRel(0, 1)\n");
	schedtbl_value = -1;
	schedtbl_cycle = 5;
	for (counter_value = 1; counter_value <= 18; counter_value++) {
		SEQUENCE_RECORD_VALUE(counter_value, "");
		magic = 0;
		if (schedtbl_cycle >= 0) {
			schedtbl_value = schedtbl_value + 1;
		}
		if ((schedtbl_cycle > 0) && (schedtbl_value >= schedtbl_cycle)) {
			schedtbl_value = schedtbl_value - schedtbl_cycle;
		}
		if (schedtbl_value < 0) {
			printk("%2d    : ", counter_value);
		} else {
			printk("%2d (%d): ", counter_value, schedtbl_value);
		}
		IncrementCounter(IdCounter);

		while (magic < 4) {
			printk("\t");
			magic++;
		}

		switch (counter_value) {
		case 8:
			printk("StopScheduleTable(0)");
			StopScheduleTable(0);
			schedtbl_value = -100;
			schedtbl_cycle = -1;
			break;
		case 10:
			printk("StartScheduleTableAbs(0, 9)");
			StartScheduleTableAbs(0, 9);
			schedtbl_value = 1;
			schedtbl_cycle = 5;
			break;
		case 12:
			printk("NextScheduleTable(0, 1)");
			NextScheduleTable(0, 1);
			break;
		}
		printk("\n");
	}

	ASSERT_SEQUENCE(basic_scheduletable_sequence_right);
}

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
TEST(sync_scheduletable)
{
	VAR(int32_t, AUTOMATIC) counter_value;
	VAR(int32_t, AUTOMATIC) sync_value = -1;
	VAR(int32_t, AUTOMATIC) sync_cycle = -1;

	DeclareCounter(IdCounter, 1024, 1, 1, SOFTWARE);
	DeclareScheduleTable(IdScheduleTable0, 10, 10, IdCounter, EXPLICIT, 1);
	DeclareExpiryPoint(0, 2, IdScheduleTable0, 1, 2);
	DeclareExpiryPoint(1, 5, IdScheduleTable0, 1, 2);
	DeclareExpiryPoint(2, 8, IdScheduleTable0, 1, 2);
	DeclareExpiryPointTask(0, IdTestTask9, 0);
	DeclareExpiryPointEvent(0, IdTestTask9, EVENT9_1, 1);
	DeclareExpiryPointEvent(1, IdTestTask9, EVENT9_2, 2);

	LOGI("同步调度表测试开始\n");
	LOGI("调度表0,周期10,循环,显式同步,在2,5,8时刻有到期点\n");
	LOGI("2时刻激活task9，5、6时刻分别设置事件1、2\n");
	LOGI("每个到期点可以提前1个时刻，延后2个时刻\n");
	LOGI("此处测试场景参考 \"AUTOSAR_SWS_OS\"中Figure 7.8:\n");
	LOGI("  ExplicitSchedule Table Synchronization\n");

	LOGI("以下第一列数字是驱动计数器的值\n");
	LOGI("  括号中的数字是同步计数器的值\n");
	LOGI("  中间两列已激活和事件唤醒的字样来自激活或唤醒的任务输出\n");
	LOGI("  最后一列是当时调用的接口及参数\n");

	StartScheduleTableSynchron(0);
	magic = 0;
	while (magic < 5) {
		printk("\t");
		magic++;
	}
	printk("StartScheduleTableSynchron(0)\n");
	for (counter_value = 1; counter_value <= 35; counter_value++) {
		SEQUENCE_RECORD_VALUE(counter_value, "");
		magic = 0;

		if (sync_cycle >= 0) {
			sync_value = sync_value + 1;
		}
		if ((sync_cycle > 0) && (sync_value >= sync_cycle)) {
			sync_value = sync_value - sync_cycle;
		}
		if (sync_value < 0) {
			printk("%2d    : ", counter_value);
		} else {
			printk("%2d (%d): ", counter_value, sync_value);
		}

		IncrementCounter(IdCounter);

		while (magic < 4) {
			printk("\t");
			magic++;
		}

		switch (counter_value) {
		case 3:
			printk("SyncScheduleTable(0, 8)");
			SyncScheduleTable(0, 8);
			sync_value = 8;
			sync_cycle = 10;
			break;
		case 12:
			printk("SyncScheduleTable(0, 5)");
			SyncScheduleTable(0, 5);
			sync_value = 5;
			break;
		case 28:
			printk("SyncScheduleTable(0, 3)");
			SyncScheduleTable(0, 3);
			sync_value = 3;
			break;
		}
		printk("\n");
	}

	ASSERT_SEQUENCE(sync_scheduletable_sequence_right);
}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */


TASK(TestTask7, app0)
{
	SEQUENCE_RECORD_VALUE(TASK7_ACTIVATED, "");
	printk("task7已激活\t");
	magic += 2;

	WaitEvent(EVENT7_1);
	SEQUENCE_RECORD_VALUE(TASK7_EVENT_WAKEUP, "");
	while (magic < 2) {
		printk("\t");
		magic++;
	}
	printk("task7事件唤醒\t");
	magic += 2;

	TerminateTask();
}

TASK(TestTask8, app0)
{
	SEQUENCE_RECORD_VALUE(TASK8_ACTIVATED, "");
	printk("task8已激活\t");
	magic += 2;

	TerminateTask();
}

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
TASK(TestTask9, app0)
{
	SEQUENCE_RECORD_VALUE(TASK9_ACTIVATED, "");
	printk("task9已激活\t");
	magic += 2;

	WaitEvent(EVENT9_1);
	SEQUENCE_RECORD_VALUE(TASK9_EVENT_WAKEUP1, "");
	while (magic < 2) {
		printk("\t");
		magic++;
	}
	printk("task9得到事件1\t");

	WaitEvent(EVENT9_2);
	SEQUENCE_RECORD_VALUE(TASK9_EVENT_WAKEUP2, "");
	while (magic < 2) {
		printk("\t");
		magic++;
	}
	printk("task9得到事件2\t");

	TerminateTask();
}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */


TEST_SUIT(scheduletable)
{
	FUNCTEST_CASE(basic_scheduletable);
#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	FUNCTEST_CASE(sync_scheduletable);
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
}

